package ceph

import (
	"bytes"
	"fmt"
	"io"
	"strings"
	"sync"
	"yunpan/db"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
)

var cephConn StorageSession
var mu sync.RWMutex

type StorageSession struct {
	s3session *s3.S3
	Url       string
	S3key     string
	Secret    string
	Region    string
	Bucket    string
}

func GetCephAdminConn() (*StorageSession, error) {
	// 确保数据库已初始化
	if db.DB == nil {
		if err := db.InitDB(); err != nil {
			return nil, err
		}
	}

	mu.Lock()
	defer mu.Unlock()

	user, err := db.GetUserInfo("admin")
	if err != nil {
		return nil, err
	}
	cephConn.S3key = user.AccessKey
	cephConn.Secret = user.SecretKey
	cephConn.Region = "us-east-1"
	cephConn.Url = "http://192.168.1.224:80"
	creds := credentials.NewStaticCredentials(cephConn.S3key, cephConn.Secret, "")
	// 创建一个新的 S3 客户端实例
	cephConn.s3session = s3.New(session.New(), aws.NewConfig().
		WithEndpoint(cephConn.Url).
		WithS3ForcePathStyle(true).
		WithRegion(cephConn.Region).
		WithCredentials(creds))

	return &cephConn, nil
}

func GetCephConn(username string) (*StorageSession, error) {

	user, err := db.GetUserInfo(username)
	if err != nil {
		return nil, err
	}
	localCephConn := new(StorageSession)
	localCephConn.Bucket = fmt.Sprintf("%s-default", username)
	localCephConn.S3key = user.AccessKey
	localCephConn.Secret = user.SecretKey
	localCephConn.Region = "us-east-1"
	localCephConn.Url = "http://192.168.1.224:80"
	creds := credentials.NewStaticCredentials(localCephConn.S3key, localCephConn.Secret, "")
	// 创建一个新的 S3 客户端实例
	localCephConn.s3session = s3.New(session.New(), aws.NewConfig().
		WithEndpoint(localCephConn.Url).
		WithS3ForcePathStyle(true).
		WithRegion(localCephConn.Region).
		WithCredentials(creds))

	return localCephConn, nil

}

func GetBuckets(username string) error {
	// 获取 Ceph S3 客户端
	cephConn, err := GetCephConn(username)
	if err != nil {
		return err
	}

	// 列出所有桶
	result, err := cephConn.s3session.ListBuckets(&s3.ListBucketsInput{})
	if err != nil {
		return err
	}

	// 打印桶名
	for _, bucket := range result.Buckets {
		fmt.Println(*bucket.Name)
	}

	return nil
}

// UploadObject 上传对象到指定的 Ceph S3 桶

func (session *StorageSession) UploadObject(objectKey string, content []byte) error {
	// 注意这里不再需要 username 参数，因为 bucket 信息已经在 session 中
	// bucketName := fmt.Sprintf("%s-default", session.Username)  // 需要在结构体中添加 Username 字段

	buffer := bytes.NewReader(content)
	_, err := session.s3session.PutObject(&s3.PutObjectInput{
		Bucket: aws.String(session.Bucket),
		Key:    aws.String(objectKey),
		Body:   buffer,
	})

	if err != nil {
		return fmt.Errorf("上传对象 %s 失败: %v", objectKey, err)
	}
	return nil
}

func (session *StorageSession) DeleteObject(key string) error {
	// 如果是文件夹，需要删除文件夹下的所有文件
	if strings.HasSuffix(key, "/") || session.isFolder(key) {
		// 列出文件夹下的所有对象
		input := &s3.ListObjectsV2Input{
			Bucket: aws.String(session.Bucket),
			Prefix: aws.String(key), // 使用文件夹路径作为前缀
		}

		err := session.s3session.ListObjectsV2Pages(input, func(page *s3.ListObjectsV2Output, lastPage bool) bool {
			for _, obj := range page.Contents {
				// 删除每个对象
				_, delErr := session.s3session.DeleteObject(&s3.DeleteObjectInput{
					Bucket: aws.String(session.Bucket),
					Key:    obj.Key,
				})
				if delErr != nil {
					fmt.Printf("删除对象失败 %s: %v\n", *obj.Key, delErr)
				}
			}
			return true // 继续处理下一页
		})

		if err != nil {
			fmt.Printf("列出文件夹内容失败 %s: %v\n", key, err)
			return err
		}
	}

	// 删除对象本身
	_, err := session.s3session.DeleteObject(&s3.DeleteObjectInput{
		Bucket: aws.String(session.Bucket),
		Key:    aws.String(key),
	})

	if err != nil {
		fmt.Printf("path: %s, DeleteObject操作失败: %v\n", key, err)
		return err
	}
	fmt.Printf("path: %s, DeleteObject操作成功\n", key)
	return nil
}

// 判断是否为文件夹
func (session *StorageSession) isFolder(key string) bool {
	// 检查是否存在以该key为前缀的其他对象
	input := &s3.ListObjectsV2Input{
		Bucket:  aws.String(session.Bucket),
		Prefix:  aws.String(key),
		MaxKeys: aws.Int64(1), // 只需要检查是否存在至少一个对象
	}

	result, err := session.s3session.ListObjectsV2(input)
	if err != nil {
		return false
	}

	return len(result.Contents) > 0
}

// DownloadObject 从 Ceph 下载对象
func (session *StorageSession) DownloadObject(objectKey string) ([]byte, error) {
	// 获取对象
	result, err := session.s3session.GetObject(&s3.GetObjectInput{
		Bucket: aws.String(session.Bucket),
		Key:    aws.String(objectKey),
	})

	if err != nil {
		return nil, fmt.Errorf("下载对象 %s 失败: %v", objectKey, err)
	}
	defer result.Body.Close()

	// 读取对象内容
	data, err := io.ReadAll(result.Body)
	if err != nil {
		return nil, fmt.Errorf("读取对象内容失败: %v", err)
	}

	return data, nil
}

// GetObjectReader 获取对象的读取器
func (session *StorageSession) GetObjectReader(objectKey string) (io.ReadCloser, error) {
	result, err := session.s3session.GetObject(&s3.GetObjectInput{
		Bucket: aws.String(session.Bucket),
		Key:    aws.String(objectKey),
	})

	if err != nil {
		return nil, fmt.Errorf("获取对象读取器失败 %s: %v", objectKey, err)
	}

	return result.Body, nil
}

// UploadStream 上传流数据
func (session *StorageSession) UploadStream(objectKey string, reader io.Reader) error {
	// 先读取所有数据到 buffer
	var buf bytes.Buffer
	if _, err := io.Copy(&buf, reader); err != nil {
		return fmt.Errorf("读取流数据失败: %v", err)
	}

	// 使用 bytes.Reader，它实现了 io.ReadSeeker 接口
	bodyReader := bytes.NewReader(buf.Bytes())

	_, err := session.s3session.PutObject(&s3.PutObjectInput{
		Bucket: aws.String(session.Bucket),
		Key:    aws.String(objectKey),
		Body:   bodyReader,
	})

	if err != nil {
		return fmt.Errorf("上传流数据失败 %s: %v", objectKey, err)
	}
	return nil
}
